package com.boot2.core.utils;

import javax.servlet.http.HttpServletRequest;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;


/**
 * api加密
 *
 * @author zhangweilin
 * @version V1.0
 * @date 2016年11月12日 上午11:22:10
 * @description
 */
public class UrlEncryptUtil {

    /**
     * 拼装成查询字符串
     *
     * @param paramMap
     * @param excludedKey 要排除的特殊key
     * @return
     */
    public static String getParameterString(Map<?, ?> paramMap, String... excludedKey) {
        // System.out.println("ps: " + ps);
        MapNumberKeyComparator<String> bvc = new MapNumberKeyComparator<>(MapNumberKeyComparator.Order.asc);
        TreeMap<String, Object> sortedMap = new TreeMap<>(bvc);
        sortedMap.putAll((Map<? extends String, ? extends Object>) paramMap);
        // System.out.println("sortedMap: " + sortedMap);

        StringBuffer sb = new StringBuffer();
        for (Iterator<?> iterator = sortedMap.keySet().iterator(); iterator.hasNext(); ) {
            boolean isIgnore = false;
            String key = (String) iterator.next();
            if (excludedKey != null) {
                for (int i = 0; i < excludedKey.length; i++) {
                    if (key.equalsIgnoreCase(excludedKey[i])) {
                        isIgnore = true;
                        continue;
                    }
                }
            }

            if (isIgnore) {
                continue;
            }

            Object o = paramMap.get(key);
			if (o == null) {
				o = "";
			}
            String[] values = null;
            if (o instanceof String[]) {
                values = (String[]) o;
            } else {
                values = new String[]{o.toString()};
            }

            String[] as;
            int j = (as = values).length;
            for (int i = 0; i < j; ++i) {
                String value = as[i];
                sb.append(key).append("=").append(value).append("&");
            }
        }

        // System.out.println("sb.toString(): " + sb.toString());
        if ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == '&')) {
            return sb.substring(0, sb.length() - 1);
        }

        return sb.toString();
    }

    /**
     * 拼装成查询字符串
     *
     * @param paramMap
     * @param excludedKey 要排除的特殊key
     * @return
     */
    public static String getParameterString1(Map<String, Object> paramMap, String... excludedKey) {
        // System.out.println("ps: " + ps);
        MapNumberKeyComparator<String> bvc = new MapNumberKeyComparator<>(MapNumberKeyComparator.Order.asc);
        TreeMap<String, Object> sortedMap = new TreeMap<>(bvc);
        sortedMap.putAll(paramMap);
        // System.out.println("sortedMap: " + sortedMap);

        StringBuffer sb = new StringBuffer();
        for (Iterator<?> iterator = sortedMap.keySet().iterator(); iterator.hasNext(); ) {
            boolean isIgnore = false;
            String key = (String) iterator.next();
            if (excludedKey != null) {
                for (int i = 0; i < excludedKey.length; i++) {
                    if (key.equalsIgnoreCase(excludedKey[i])) {
                        isIgnore = true;
                        continue;
                    }
                }
            }

            if (isIgnore) {
                continue;
            }
            String value = (String) paramMap.get(key);
            sb.append(key).append("=").append(value).append("&");
        }

        // System.out.println("sb.toString(): " + sb.toString());
        if ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == '&')) {
            return sb.substring(0, sb.length() - 1);
        }

        return sb.toString();
    }

    /**
     * @param paramMap
     * @param encryptKey  加密key
     * @param excludedKey 排除的参数名
     * @return
     */
    public static String encrypt(Map<?, ?> paramMap, String encryptKey, String... excludedKey) {
        String str = getParameterString(paramMap, excludedKey);
        return encrypt(str, encryptKey);
    }

    /**
     * 没有参数的，暂时不考虑加密
     *
     * @param request
     * @param encryptKey
     * @param excludedKey
     * @return
     */
    public static boolean checkApiValid(HttpServletRequest request, String encryptKey, String... excludedKey) {
        String sign = request.getParameter("sign");
        String str = encrypt(request.getParameterMap(), encryptKey, excludedKey);
        if (StringUtils.isEmpty(str)) {
            return true;
        }
        if (str.equals(sign)) {
            // System.out.println("url合法");
            return true;
        } else {
            return false;
        }
    }

    private static String encrypt(String str, String encryptKey) {
        // 没有参数的暂不加密
        System.out.println("str: " + str);
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        str = str + str.length() * 2014 + encryptKey;
        str = MD5.encode(str);
        str = MD5.encode(str + encryptKey);
        System.out.println("str: " + str);
        return str;
    }
}

/**
 * 对map的key进行排序,在不传order排序方向情况下， 默认情况下，是从小到大的
 *
 * @author zhangweilin
 * @version V1.0
 * @date 2016年5月30日 下午2:41:46
 * @description
 */
class MapNumberKeyComparator<T> implements Comparator<T> {
    protected Order order = Order.asc;

    // 排序方向
    public static enum Order {
        desc("倒序", -1), asc("正序", 1);

        protected String name;
        protected int sign;

        private Order(String name, int sign) {
            this.name = name;
            this.sign = sign;
        }

        public static String getName(int sign) {
            for (Order c : Order.values()) {
                if (c.getSign() == sign) {
                    return c.name;
                }
            }
            return null;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getSign() {
            return sign;
        }

        public void setSign(int sign) {
            this.sign = sign;
        }
    }

    public MapNumberKeyComparator() {
    }

    public MapNumberKeyComparator(Order order) {
        this.order = order;
    }

    // Note: this comparator imposes orderings that are inconsistent with
    // equals.
    @Override
    public int compare(T a, T b) {
        Long aa = null, bb = null;

        // String类型
        if (a instanceof String && b instanceof String) {
            String aStr = (String) a;
            String bStr = (String) b;
            return aStr.compareToIgnoreCase(bStr) * order.sign;

        } else if (a instanceof Number && b instanceof Number) {
            aa = (Long) a;
            bb = (Long) b;
        } else {
            throw new RuntimeException("指定按key排序时，key暂时只支持意义上的数字类型");
        }

        if (aa >= bb) {
            return 1 * order.sign;
        } else {
            return -1 * order.sign;
        }
    }
}
